﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.SharePoint.Administration;

namespace Ahmad.A.Ousman.DotNetExtensions.Logging.SharePoint
{
    /// <summary>
    /// SharePoint Log Service
    /// </summary>
    public class SharePointLogService : SPDiagnosticsServiceBase
    {
        #region Constants
        private const string INFO = "Info";
        private const string ERROR = "Error";
        #endregion

        #region Read Only Fieds
        private static readonly string DIAGNOSTIC_NAME = Assembly.GetExecutingAssembly().GetName().Name;
        #endregion

        #region Private Fields
        private static List<string> _products;
        private static SharePointLogService _current;
        #endregion

        #region Constructor(s)
        private SharePointLogService() : base(DIAGNOSTIC_NAME, SPFarm.Local) { _products = new List<string>(); }
        #endregion

        #region Properties
        static SharePointLogService Current
        {
            get { return _current ?? (_current = new SharePointLogService()); }
        }
        static SPDiagnosticsArea DefaultArea
        {
            get { return GetDiagnosticsArea(DIAGNOSTIC_NAME); }
        }
        #endregion

        #region Methods
        protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
        {
            var areas = new List<SPDiagnosticsArea>();
            var categories = new List<SPDiagnosticsCategory> { new SPDiagnosticsCategory(INFO, TraceSeverity.Verbose, EventSeverity.Information), new SPDiagnosticsCategory(ERROR, TraceSeverity.Unexpected, EventSeverity.Error) };
            _products.ForEach(product => areas.Add(new SPDiagnosticsArea(product, categories)));
            return areas;
        }

        static SPDiagnosticsArea GetDiagnosticsArea(string product)
        {
            EnsureProduct(product);
            return Current.Areas[product];
        }

        static void EnsureProduct(string product)
        {
            if (!_products.Exists(match => match.Equals(product, StringComparison.InvariantCultureIgnoreCase)))
            {
                _products.Add(product);
            }
        }

        /// <summary>
        /// This method logs message to SharePoint Log
        /// </summary>
        /// <param name="message"></param>
        public static void LogMessage(string message)
        {
            LogMessage(DIAGNOSTIC_NAME, message);
        }

        /// <summary>
        /// This method logs message to SharePoint Log
        /// </summary>
        /// <param name="product"></param>
        /// <param name="message"></param>
        public static void LogMessage(string product, string message)
        {
            var defaultArea = GetDiagnosticsArea(product) ?? DefaultArea;
            if (defaultArea != null)
            {
                var category = defaultArea.Categories[INFO];
                if (category != null)
                {
                    Current.WriteTrace(0, category, TraceSeverity.Verbose, message);
                }
            }
        }

        /// <summary>
        /// This method logs message to SharePoint Log
        /// </summary>
        /// <param name="message"></param>
        public static void LogError(string message) { LogError(DIAGNOSTIC_NAME, message); }

        /// <summary>
        /// This method logs message to SharePoint Log
        /// </summary>
        /// <param name="product"></param>
        /// <param name="message"></param>
        public static void LogError(string product, string message)
        {
            var defaultArea = GetDiagnosticsArea(product) ?? DefaultArea;
            if (defaultArea != null)
            {
                var category = defaultArea.Categories[ERROR];
                if (category != null)
                {
                    Current.WriteTrace(0, category, TraceSeverity.Unexpected, message);
                }
            }
        }
        #endregion
    }
}
